package is.progetto1.aritmeticExpression.builder.impl;

import java.io.IOException;

import is.progetto1.aritmeticExpression.Expression;
import is.progetto1.aritmeticExpression.Utility;
import is.progetto1.aritmeticExpression.builder.DirectorIF;
import is.progetto1.aritmeticExpression.builder.ExpressionBuilderIF;
import is.progetto1.aritmeticExpression.builder.InputManagerIF;

public class DirectorR implements DirectorIF {
	 
	private InputManagerIF im=null;
	private String symble=null;
	private ExpressionBuilderIF eb;
	private int nbrake=0;
	
	public DirectorR(InputManagerIF im, ExpressionBuilderIF eb){
		this.im=im;
		this.eb=eb;
	}
	
	@Override
	public Expression costruct() throws IOException {
		this.add();
		return eb.getResult();
	}

	private void add() throws IOException{
		sub();
		while(symble.equals("+")){
			eb.fixOperator("+");
			sub();
		}
	}

	private void sub() throws IOException {
		mul();
		while(symble.equals("-")){
			eb.fixOperator("-");
			mul();
		}
	}

	private void mul() throws IOException {
		div();
		while(symble.equals("*")){
			eb.fixOperator("*");
			div();
		}
	}

	private void div() throws IOException {
		operator();
		while(symble.equals("/")){
			eb.fixOperator("/");
			operator();
		}
	}

	private void operator() throws IOException {
		operant();
		while(symble.equals("(")){
			eb.buildOperator();
			nbrake++;
			operant();
		}
		while(symble.equals(")")){
			eb.endsOperator();
			nbrake--;
			operant();
		}
	}

	private void operant() throws IOException {
		this.symble=im.nextSymble();
		if(this.symble.equals(InputManager.EOS)){
			return;
		}
		if (symble.matches(Utility.REGEX_NUMBER)||symble.matches(Utility.REGEX_VARIABLE)) {
			if(nbrake==0){
				throw new IOException();
			}
			this.eb.buildOperand(this.symble);
			operant();
		}if(symble.equals("+")||symble.equals("-")||symble.equals("*")||symble.equals("/")||symble.equals("(")||symble.equals(")")){
			return;
		}else{
			throw new IOException(this.symble+" inaspected");
		}
	}
	
}
